import 'dart:async';

import 'package:http/http.dart' as http;
import 'package:http/src/boundary_characters.dart';
import 'package:http_parser/http_parser.dart';

import '../common/test_page.dart';

class MultipartTestPage extends TestPage {
  MultipartTestPage(super.title) {
    test('http.MultipartRequest(super.method, super.url)', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      expect(request, '''
        --{{boundary}}--
        ''');
    });

    test('MediaType.parse("text/plain; boundary=String.fromCharCodes(boundaryCharacters)").parameters["boundary"]', () {
      var testBoundary = String.fromCharCodes(boundaryCharacters);
      var contentType = MediaType.parse('text/plain; boundary=$testBoundary');
      var boundary = contentType.parameters['boundary'];
      expect(boundary, testBoundary);
    });

    test('http.MultipartRequest(), http.MultipartFile.fromString(String field, String value,{String? filename, MediaType? contentType})', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.fields['field1'] = 'value1';
      request.fields['field2'] = 'value2';
      request.files.add(http.MultipartFile.fromString('file1', 'contents1',
          filename: 'filename1.txt'));
      request.files.add(http.MultipartFile.fromString('file2', 'contents2'));

      expect(request, '''
        --{{boundary}}
        content-disposition: form-data; name="field1"

        value1
        --{{boundary}}
        content-disposition: form-data; name="field2"

        value2
        --{{boundary}}
        content-type: text/plain; charset=utf-8
        content-disposition: form-data; name="file1"; filename="filename1.txt"

        contents1
        --{{boundary}}
        content-type: text/plain; charset=utf-8
        content-disposition: form-data; name="file2"

        contents2
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换带有unicode字段名', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.fields['fïēld'] = 'value';

      expect(request, '''
        --{{boundary}}
        content-disposition: form-data; name="fïēld"

        value
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换带有换行符的字段名', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.fields['foo\nbar\rbaz\r\nbang'] = 'value';

      expect(request, '''
        --{{boundary}}
        content-disposition: form-data; name="foo%0D%0Abar%0D%0Abaz%0D%0Abang"

        value
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换带有带引号的字段名', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.fields['foo"bar'] = 'value';

      expect(request, '''
        --{{boundary}}
        content-disposition: form-data; name="foo%22bar"

        value
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换具有unicode字段值', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.fields['field'] = 'vⱥlūe';

      expect(request, '''
        --{{boundary}}
        content-disposition: form-data; name="field"
        content-type: text/plain; charset=utf-8
        content-transfer-encoding: binary

        vⱥlūe
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换带有unicode文件名', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.files.add(http.MultipartFile.fromString('file', 'contents',
          filename: 'fïlēname.txt'));

      expect(request, '''
        --{{boundary}}
        content-type: text/plain; charset=utf-8
        content-disposition: form-data; name="file"; filename="fïlēname.txt"

        contents
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()带有换行符的文件名', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.files.add(http.MultipartFile.fromString('file', 'contents',
          filename: 'foo\nbar\rbaz\r\nbang'));

      expect(request, '''
        --{{boundary}}
        content-type: text/plain; charset=utf-8
        content-disposition: form-data; name="file"; filename="foo%0D%0Abar%0D%0Abaz%0D%0Abang"

        contents
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换带有带引号的文件名', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      request.files.add(
          http.MultipartFile.fromString('file', 'contents', filename: 'foo"bar'));

      expect(request, '''
        --{{boundary}}
        content-type: text/plain; charset=utf-8
        content-disposition: form-data; name="file"; filename="foo%22bar"

        contents
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换包含一个具有内容类型但没有字符集的字符串文件', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      var file = http.MultipartFile.fromString('file', '{"hello": "world"}',
          contentType: MediaType('application', 'json'));
      request.files.add(file);

      expect(request, '''
        --{{boundary}}
        content-type: application/json; charset=utf-8
        content-disposition: form-data; name="file"

        {"hello": "world"}
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()替换带有iso-8859-1正文的文件', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      // "Ã¥" encoded as ISO-8859-1 and then read as UTF-8 results in "å".
      var file = http.MultipartFile.fromString('file', 'non-ascii: "Ã¥"',
          contentType: MediaType('text', 'plain', {'charset': 'iso-8859-1'}));
      request.files.add(file);

      expect(request, '''
        --{{boundary}}
        content-type: text/plain; charset=iso-8859-1
        content-disposition: form-data; name="file"

        non-ascii: "å"
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()使用流文件', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      var controller = StreamController<List<int>>(sync: true);
      request.files.add(http.MultipartFile('file', controller.stream, 5));

      expect(request, '''
        --{{boundary}}
        content-type: application/octet-stream
        content-disposition: form-data; name="file"

        hello
        --{{boundary}}--
        ''');

      controller
        ..add([104, 101, 108, 108, 111])
        ..close();
    });

    test('http.MultipartRequest()使用具有空流文件', () {
      var request = http.MultipartRequest('POST', Uri.parse('http://httpbin.org/post'));
      var controller = StreamController<List<int>>(sync: true);
      request.files.add(http.MultipartFile('file', controller.stream, 0));

      expect(request, '''
        --{{boundary}}
        content-type: application/octet-stream
        content-disposition: form-data; name="file"


        --{{boundary}}--
        ''');

      controller.close();
    });

    test('http.MultipartRequest()使用带有字节文件', () {
      var request = http.MultipartRequest('POST', Uri.parse('https://httpbin.org/post'));
      var file = http.MultipartFile.fromBytes('file', [104, 101, 108, 108, 111]);
      request.files.add(file);

      expect(request, '''
        --{{boundary}}
        content-type: application/octet-stream
        content-disposition: form-data; name="file"

        hello
        --{{boundary}}--
        ''');
    });

    test('http.MultipartRequest()使用有错误的文件', () async {
      var file = http.MultipartFile(
          'file', Future<List<int>>.error('error').asStream(), 1);
      var request = http.MultipartRequest('POST', Uri.parse('https://httpbin.org/post'))..files.add(file);
      expect(request.finalize().drain<void>(), 'error');
    });
  }

}